/* **********************************************************
 * Copyright 2010 Dimitar Vangelovski
 *
 * This file is part of the Gens3 3D Engine.
 * 
 * The Gens3 3D Engine is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 * 
 * The Gens3 3D Engine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with the Gens3 3D Engine; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 * **********************************************************/


#pragma once

#include <string>
#include <vector>
#include <stack>

class CScene;
class CMaterial;
class CMapDiffuse;
class CSubMaterial;
class CGeomObject;
class CMesh;
class CMeshTVertList;
class CMeshTFaceList;
class CLightObject;
class CAnimObject;

static const int g_iGeneralASETagsCount = 56;
static const std::string g_strGeneralASETags[g_iGeneralASETagsCount] = 
{
	"*SCENE_FILENAME ",

	// Material tags
	"*MATERIAL_LIST {",
	"*MATERIAL_COUNT ",
	"*MATERIAL ",
	"*MATERIAL_NAME ",
	"*MATERIAL_AMBIENT ",
	"*MATERIAL_DIFFUSE ",
	"*MATERIAL_SPECULAR ",
	"*MATERIAL_SHINE ",
	"*MATERIAL_SHINESTRENGTH ",
	"*MATERIAL_TRANSPARENCY ",
	"*MATERIAL_SELFILLUM ",
	"*MAP_DIFFUSE {",
	"*NUMSUBMTLS",
	"*MAP_NAME ",
	"*BITMAP ",
	"*UVW_U_OFFSET ",
	"*UVW_V_OFFSET ",
	"*UVW_U_TILING ",
	"*UVW_V_TILING ",
	"*SUBMATERIAL ",

	// GeomObject tags
	"*GEOMOBJECT {",
	"*NODE_NAME ",
	"*MESH {",
	"*MESH_NUMVERTEX ",
	"*MESH_NUMFACES ",
	"*MESH_VERTEX_LIST {",
	"*MESH_VERTEX ",
	"*MESH_FACE_LIST {",
	"*MESH_FACE ",
	"*MESH_NUMTVERTEX ",
	"*MESH_TVERTLIST {",
	"*MESH_TVERT ",
	"*MESH_NUMTVFACES ",
	"*MESH_TFACELIST {",
	"*MESH_TFACE ",
	"*MESH_NUMCVERTEX ",
	"*MESH_NORMALS {",
	"*MESH_FACENORMAL ",
	"*MESH_VERTEXNORMAL ",
	"*PROP_CASTSHADOW ",
	"*PROP_RECVSHADOW ",
	"*MATERIAL_REF ",

	// LightObject tags
	"*LIGHTOBJECT {",
	"*NODE_NAME ",
	"*TM_POS ",
	"*LIGHT_SHADOWS Off",
	"*LIGHT_SHADOWS Mapped",
	"*LIGHT_SHADOWS Raytraced",
	"*LIGHT_USELIGHT ",
	"*LIGHT_COLOR ",
	"*LIGHT_INTENS ",
	"*LIGHT_ATTNEND",

	"{",
	"}",

	"*NODE_PARENT ",
};

static const int g_iAnimateTagsCount = 2;
static const std::string g_strAnimateTags[g_iAnimateTagsCount] = 
{
	"Rotate",
	"Translate",
};

class CLoaderASE
{
public:

	enum eGeneralASETags
	{
		eUnknownTag = -1,
		eSceneFilename,

		// Material tags
		eMaterialList,
		eMaterialCount,
		eMaterial,
		eMaterialName,
		eMaterialAmbient,
		eMaterialDiffuse,
		eMaterialSpecular,
		eMaterialShine,
		eMaterialShineStrength,
		eMaterialTransparency,
		eMaterialSelfIllum,
		eMapDiffuse,
		eNumSubMtls,
		eMapName,
		eBitmap,
		eUVW_U_Offset,
		eUVW_V_Offset,
		eUVW_U_Tiling,
		eUVW_V_Tiling,
		eSubMaterial,

		// GeomObject tags
		eGeomObject,
		eNodeName,
		eMesh,
		eMeshNumVertex,
		eMeshNumFaces,
		eMeshVertexList,
		eMeshVertex,
		eMeshFaceList,
		eMeshFace,
		eMeshNumTVertex,
		eMeshTVertList,
		eMeshTVert,
		eMeshNumTVFaces,
		eMeshTFaceList,
		eMeshTFace,
		eMeshNumCVertex,
		eMeshNormals,
		eMeshFaceNormal,
		eMeshVertexNormal,
		ePropCastShadow,
		ePropRecvShadow,
		eMaterialRef,

		// LightObject tags
		eLightObject,
		eLightNodeName,
		eTmPos,
		eLightShadowsOff,
		eLightShadowsMapped,
		eLightShadowsRaytraced,
		eLightUseLight,
		eLightColor,
		eLightIntens,
		eLightAttnend,

		eOpeningBrace,
		eClosingBrace,

		eNodeParent,
	};

	enum eCurrentObjectIndicator
	{
		eUndefinedInd = -1,
		eMaterialInd,
		eSubMaterialInd,
		eGeomObjectInd,
		eLightObjectInd,
	};

	enum eAnimateTags
	{
		eAnimUnknownTag = -1,
		eAnimRotate,
		eAnimTranslate,
	};

public:
	CLoaderASE();
	~CLoaderASE();

	void		OpenFile(const char * fileName);
	void		CloseFile();
	void		ParseFile();

	CScene *	GetScene() const { return m_pScene; }

private:
	int		ReadLine(std::string &strLine);
	int		CheckTags(std::string &strLine);
	int		CheckTagsAnimate(std::string &strLine);
	bool	ParseAnimationParms(std::string strLine);
	void	ParseLine(char * pString, const char * pDelimiter, std::vector<std::string> &strTokens);

private:
	const char *        m_pFileName;
	FILE *              m_theFile;
	char *              m_theBuffer;
	std::stack<char>	m_theStack;	// a stack to keep track of the curly braces "{}" nested structures

	CScene *            m_pScene;
	CMaterial *         m_pMaterial;
	CMapDiffuse *		m_pMapDiffuse;
	CSubMaterial *		m_pSubMaterial;

	CGeomObject *		m_pGeomObject;
	CMesh *				m_pMesh;
	CMeshTVertList *	m_pMeshTVertList;
	CMeshTFaceList *	m_pMeshTFaceList;

	CLightObject *		m_pLightObject;
	CAnimObject *		m_pAnimObject;

	int			m_iMaterialCount;
	int			m_iGeomObjectCount;
	int			m_iLightObjectCount;
	int			m_iCurrentObjectIndicator;
	int			m_iAnimationObjectIndicator;
};
